package common

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

//请求客户端
type TcpClient struct {
	net.Conn
	reader *bufio.Reader
}

//构建请求客户端
func NewTCPClient(server string) *TcpClient {
	c, e := net.Dial("tcp", server)
	if e != nil {
		return nil
	}
	r := bufio.NewReader(c)
	return &TcpClient{c, r}
}

//构建可重连请求客户端
func NewReconTCPClient(server string) *TcpClient {
	failCount := 0
reconn:
	//重连的时候方法连接超时时间
	//times := 4
	//fmt.Println("time:", time.Now())
	//BUG(Yuxiang Wan) windows10 go1.15版本，设置读取超时时间无效，不管设置多长，最大2秒就返回了
	c, e := net.DialTimeout("tcp", server, 2*time.Second)
	//fmt.Println(time.Now())
	if e != nil {
		failCount++
		//重连10次，如果还不成功，那么直接返回nil
		if failCount > 10 {
			return nil
		}
		goto reconn
	}
	r := bufio.NewReader(c)
	return &TcpClient{c, r}
}

func (client *TcpClient) sendDel(key, value string) (n int, err error) {
	klen := len(key)
	vlen := len(value)
	return client.Write([]byte(fmt.Sprintf("D%d %d %s%s", klen, vlen, key, value)))
}

func (client *TcpClient) sendGet(key, value string) (n int, err error) {
	klen := len(key)
	vlen := len(value)
	return client.Write([]byte(fmt.Sprintf("G%d %d %s%s", klen, vlen, key, value)))
}

func (client *TcpClient) sendSet(key, value string) (n int, err error) {
	klen := len(key)
	vlen := len(value)
	return client.Write([]byte(fmt.Sprintf("S%d %d %s%s", klen, vlen, key, value)))
}

//接受客户端响应数据
func (client *TcpClient) recvResponse() (string, error) {
	tmp, e := client.reader.ReadString(' ')
	if e != nil {
		return "", e
	}
	vlen, _ := strconv.Atoi(strings.TrimSpace(tmp))
	if vlen == 0 {
		return "", nil
	}
	if vlen < 0 {
		err := make([]byte, -vlen)
		_, e := io.ReadFull(client.reader, err)
		if e != nil {
			return "", e
		}
		return "", errors.New(string(err))
	}
	value := make([]byte, vlen)
	_, e = io.ReadFull(client.reader, value)
	if e != nil {
		return "", e
	}
	return string(value), nil
}
